/*
 * BPlusTreeTest.cpp
 *
 *  Created on: 30 Sep, 2009
 *      Author: pankaj
 */

#include <iostream>
#include "BPlusTree.h"
#include "../common.h"
#include <stdlib.h>

namespace BPlusTreeUI
{
	int indexui()
	{
		unsigned char keyformat[] = {LONG};
		BPlusTree::node root;
		root.level = 0;
		root.no_of_keys = 0;
		root.data.ldata.next.ptr = NULL;
		root.data.ldata.prev.ptr = NULL;
		root.parent.ptr = NULL;
		//root.indiv_nodes = NULL;

		int rootpage;
		BPlusTree *index = NULL;
//		index = new BPlusTree(5,keyformat,1,&rootpage);
		//BPlusTree index = *bpt;

		yadbms_common::rid r;
		r.pageno = 1;
		r.slotno = 0;
		//unsigned char temp[] = {'0','0','0','2','\0'};
		long *temp = new long;
		long ins;
		int pageno;
		int slotno;
		while(true)
		{
			std::cout<<"\n1. Create Test Index\n2. Open Test Index\n3. Display Headers\n4. Insert\n5. Insert Range\n";
			std::cout<<"6. Search All\n7. Range Search\n8. Delete\n9. Delete Range\n";
			std::cout<<"10. Display Tree Node-by-Node from Root\n11. Display Node\n12. Print Tree\n";
			std::cout<<"13. Bulk Load\n0.Exit \n";
			int ch1;
			std::cin>>ch1;
			switch(ch1)
			{
			case 0:{
				index->~BPlusTree();
				return 0;

			}

			case 1:{
				if(index != NULL)
				{
					index->~BPlusTree();
				}
				cout<<"Fanout: ";
				int fan;
				cin>>fan;
				index = new BPlusTree(fan,keyformat,1,&rootpage);
				std::cout<<"Index Created with Index Header Page: "<<rootpage<<std::endl;
				break;
			}
			case 2:
			{
				std::cout<<"Index Header Page No.:\n";
				cin>>rootpage;
				if (index != NULL)
						index->~BPlusTree();
				cout<<"Fanout: ";
				int fan;
				cin>>fan;
				index = new BPlusTree(fan,keyformat,1,rootpage);
				//index = *bpt;
				break;
			}
			case 3:
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				index->printDetails();
				break;
			case 4:
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::cout<<"Number to insert:\n";

				std::cin>>ins;
				std::cout<<"Page Number to insert:\n";

				std::cin>>pageno;
				std::cout<<"Slot Number to insert:\n";

				std::cin>>slotno;
				//sprintf((char*)temp,"%8u",ins);
				*temp = ins;
				r.pageno = pageno;
				r.slotno = slotno;
				index->insert((unsigned char*)temp,r);
				//index->insert((unsigned char*)ins,r);
				//index->printTree();
				break;

			case 5:{
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}

				std::cout<<"First number of range:\n";
				long st;
				std::cin>>st;
				std::cout<<"Last number of range:\n";
				long lt;
				std::cin>>lt;
				std::cout<<"Step:\n";
				long step;
				std::cin>>step;
//				index->bulkLoad(st,lt,step);

				while(st <= lt)
				{
					//sprintf((char*)temp,"%8u",st);
					*temp = st;
					//temp[3] = st + '0';
					r.pageno = st;
					r.slotno = 0;
					st+=step;
					index->insert((unsigned char*)temp,r);
					//index->printTree();
				}
				//index->printTree();
				break;
			}
			case 6:{
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::vector<BPlusTree::searchresult> rids;
				std::cout<<"Number to search:\n";
				std::cin>>ins;
				//sprintf((char*)temp,"%8u",ins);
				*temp = ins;
				std::cout<<"Condition Select:\n";
				std::cout<<"1. =\n2. <\n3. <=\n4. >\n5. >=\n";
				int cond;
				std::cin>>cond;
				int res;// = index->rangeSearch(temp,temp1,&rids,INCLUDE,INCLUDE);
				switch(cond)
				{
				case 1:
					res = index->rangeSearch((unsigned char*)temp,NULL,&rids,EQUAL,INCLUDE);
					break;
				case 2:
					res = index->rangeSearch(NULL,(unsigned char*)temp,&rids,EQUAL,EXCLUDE);
					break;
				case 3:
					res = index->rangeSearch(NULL,(unsigned char*)temp,&rids,EQUAL,INCLUDE);
					break;
				case 4:
					res = index->rangeSearch((unsigned char*)temp,NULL,&rids,EXCLUDE,EXCLUDE);
					break;
				case 5:
					res = index->rangeSearch((unsigned char*)temp,NULL,&rids,INCLUDE,INCLUDE);
					break;
				}
				std::cout<<"Search Result:"<<std::endl;
				std::cout<<"Count:"<<res<<std::endl;
				if(res > 0)
				{
					std::cout<<"Key\tRID\n";
					for(int i=0;i<res;i++)
					{
						//					std::cout<<atoi((char*)rids[i].key)<<"\t["<<rids[i].record.pageno<<","<<rids[i].record.slotno<<"]\n";
						index->printKey(rids[i].key);
						std::cout<<"\t["<<rids[i].record.pageno<<","<<rids[i].record.slotno<<"]\n";
					}
					std::cout<<"\n";
				}

				break;
			}
			case 7:{
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::cout<<"First Number to Search:\n";
				//ins;
				std::cin>>ins;
				//sprintf((char*)temp,"%8u",ins);
				*temp = ins;
				std::cout<<"Last Number to Search:\n";
				//ins;
				std::cin>>ins;
				//unsigned char temp1[8];
				long *temp1 = new long;
				*temp1 = ins;
				//sprintf((char*)temp1,"%8u",ins);
				std::vector<BPlusTree::searchresult> rids;
				//			int res = index->search(temp,&rids);
				int res = index->rangeSearch((unsigned char*)temp,(unsigned char*)temp1,&rids,INCLUDE,INCLUDE);
				std::cout<<"Search Result:"<<std::endl;
				std::cout<<"Count:"<<res<<std::endl;
				if(res > 0)
				{
					std::cout<<"Key\tRID\n";
					for(int i=0;i<res;i++)
					{
						index->printKey(rids[i].key);
						std::cout<<"\t["<<rids[i].record.pageno<<","<<rids[i].record.slotno<<"]\n";
					}
					std::cout<<"\n";
				}
				break;
			}
			case 8:
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::cout<<"Number to Delete:\n";
				//ins;
				std::cin>>ins;
				std::cout<<"Page Number to Delete:\n";
				std::cin>>pageno;
				std::cout<<"Slot Number to Delete:\n";
				std::cin>>slotno;
				//sprintf((char*)temp,"%8u",ins);
				*temp = ins;
				r.pageno = pageno;
				r.slotno = 0;
				index->deleteEntry((unsigned char*)temp,r);
				//			index->printTree();
				break;

			case 9:{
				//TODO: Delete Range
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::cout<<"First number of range:\n";
				long st;
				std::cin>>st;
				std::cout<<"Last number of range:\n";
				long lt;
				std::cin>>lt;
				std::cout<<"Step:\n";
				long step;
				std::cin>>step;

				while(st <= lt)
				{
					//sprintf((char*)temp,"%8u",st);
					*temp = st;
					//temp[3] = st + '0';
					r.pageno = st;
					r.slotno = 0;
					st+=step;
					index->deleteEntry((unsigned char*)temp,r);
					//				index->printTree();
				}
				//index->printTree();
			}
			break;


			case 10:
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::cout<<"Root - \n";
				index->printNode(index->getRoot());
				while(true)
				{
					std::cout<<"Enter Page Number(-1 to Go Back):\n";
					int pgno;
					std::cin>>pgno;
					if(pgno == -1)
					{
						break;
					}
					BPlusTree::dp dpin;
					dpin.ptr = pgno;
					index->printNode(dpin);
				}
				break;
			case 11:
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}
				std::cout<<"Enter Page Number:\n";
				int pgno;
				std::cin>>pgno;
				BPlusTree::dp dpin;
				dpin.ptr = pgno;
				index->printNode(dpin);
				break;

			case 12:
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";break;
				}
				index->printTree();
				break;

			case 13:{
				if(index == NULL)
				{
					std::cout<<"Open/Create Index First\n";
				}

				std::cout<<"First number of range:\n";
				long st;
				std::cin>>st;
				std::cout<<"Last number of range:\n";
				long lt;
				std::cin>>lt;
				std::cout<<"Step:\n";
				long step;
				std::cin>>step;
				index->bulkLoad(st,lt,step);

				//				while(st <= lt)
				//				{
				//					//sprintf((char*)temp,"%8u",st);
				//					*temp = st;
				//					//temp[3] = st + '0';
				//					r.pageno = st;
				//					r.slotno = 0;
				//					st+=step;
				//					index->insert((unsigned char*)temp,r);
				//					//index->printTree();
				//				}
				//index->printTree();
				break;

			}
			default:
				std::cout<<"Invalid Input:\n";
				//return 0;




			}


		}
		std::cout<<"Done\n";
		return 0;
	}
}
